#include "BinaryTree_Dynamic_lyvm.h"
#include "xVMRelationStruct.h"
#include "animationCenter.h"
#include "MappingEngine.h"
#include <map>
#include <algorithm>
extern HINSTANCE _hInst ;  // this instance is defined in DIVA_MAIN
extern HWND _hWnd ;        // this instance is defined in DIVA_Application
extern string valuableNames;
extern bool bRefIn;
extern bool bRefOut;
extern int level;
extern bool bCancel_dyn;
extern bool bCancel_sta;

BOOL CALLBACK StaticLayoutDialog( HWND, UINT, WPARAM, LPARAM);

BinaryTree_Dynamic_Lyvm::BinaryTree_Dynamic_Lyvm(){
	_flag = false;
	_name = "BinaryTree Dynamic Layout";
	_root = NULL;
	animationCenter::getInstance()->addAnimation(this);
}

void BinaryTree_Dynamic_Lyvm::initial(DIVA_VM* startVM){
	/*TODO:change to Qt dialog*/
	//DialogBox( _hInst, "SLAYDIA", _hWnd, (DLGPROC)StaticLayoutDialog);
	if(bCancel_sta == true) return;
	_area = new Ly_influence_area(startVM, bRefIn, bRefOut, valuableNames, level);
	vector<DIVA_VM*> vms = _area->getAllVMs();
	searchRoot(vms);
}

void BinaryTree_Dynamic_Lyvm::setupDialog(){
/*如果需要另外建立Dialog , 請參照spring dynamic lyvm*/
}

void BinaryTree_Dynamic_Lyvm::setupParameters(){
/*建立dialog的parameters*/
}

void BinaryTree_Dynamic_Lyvm::arrangeChildsByLevel(){
	vector<DIVA_VM*> list;
	list.push_back(_root);
	int level_count = 0;
	_levels[level_count] = list;
	while(1){
		vector<DIVA_VM*>::iterator it;
		vector<DIVA_VM*> level_child;
		for(it = list.begin() ; it != list.end() ; ++it){
			vector<pair<int,DIVA_VM*>> childs = searchChildFromLink((*it));
			if(childs.size() == 0){
				continue;
			}
			vector<pair<int,DIVA_VM*>>::iterator itr;
			for(itr = childs.begin() ; itr != childs.end() ; ++itr){
				level_child.push_back((*itr).second);
			}
		}
		if(level_child.size() == 0){//下一個level沒有child , 跳出迴圈
			break;
		}
		else{
			level_count++;
			_levels[level_count] = level_child;
			list.clear();
			vector<DIVA_VM*>::iterator itr;
			for(itr = level_child.begin() ; itr != level_child.end() ; ++itr){
				list.push_back((*itr));
			}
		}
	}
}

vector<pair<int,DIVA_VM*>> BinaryTree_Dynamic_Lyvm::searchChildFromLink(DIVA_VM* node){
	linkmap::iterator it;
	vector<pair<int,DIVA_VM*>> result;
	it = _links.find(node);
	if( it != _links.end()){
		result = (*it).second;
	}
	return result;
}

void BinaryTree_Dynamic_Lyvm::insertPositionRecord(DIVA_VM* node,Ogre::Vector3 pos){
	_record[node] = pos;	
}

void BinaryTree_Dynamic_Lyvm::determineChildsPosition(DIVA_VM* root,vector<pair<int,DIVA_VM*>> childs,int level_arg){
	Ogre::Vector3 obj_size = root->getActualSize();
	obj_size.z -= root->getActualSize().z;
	positionmap::iterator pmit;
	pmit = _record.find(root);
	Ogre::Vector3 root_pos;
	if(pmit != _record.end()){
		root_pos = _record[root];
	}
	else{
		root_pos = root->getPosition();
	}
	insertPositionRecord(root,root_pos);
	Ogre::Real vertical_dis = obj_size.x;
	Ogre::Real horizontal_dis = (pow(2.0,level_arg-1)*obj_size.y)/2;
	vector<pair<int,DIVA_VM*>>::iterator it;
	for(it = childs.begin() ; it != childs.end() ; ++it){
		Ogre::Vector3 root_pos = _record[root]; 
		if((*it).first == 0){			
			Ogre::Vector3 left_final_dis = Ogre::Vector3(root_pos.x-horizontal_dis,root_pos.y-vertical_dis,0);
			//this->_record[(*it)] = left_final_dis;			
			insertPositionRecord((*it).second,left_final_dis);
		}
		else{
			Ogre::Vector3 right_final_dis = Ogre::Vector3(root_pos.x+horizontal_dis,root_pos.y-vertical_dis,0);
			//this->_record[(*it)] = right_final_dis;
			insertPositionRecord((*it).second,right_final_dis);
		}
	}
}

void BinaryTree_Dynamic_Lyvm::constructLinks(DIVA_VM* node){
	/*now , I have root , then I have to construct the link map*/
	vector<DIVA_VM*> childs = xVMRelationStruct::getInstance()->VMRS_nextVMsByRef(node);
	vector<DIVA_VM*>::iterator it;
	vector<pair<int,DIVA_VM*>> ordered_child;
	for(it = childs.begin() ; it != childs.end() ; ++it){
		vector<DIVA_VM*> preVMs = xVMRelationStruct::getInstance()->VMRS_preVMsByRef((*it));
		vector<DIVA_VM*>::iterator itr;
		for(itr = preVMs.begin() ; itr != preVMs.end() ; itr++){
			if(node->isSubComponent((*itr))){//如果找到preVMs是node的SubComponent
				OgreVM* ovm = (OgreVM*)(*itr);
				//Vector3 child_pos = ovm->getPosition();//get child pos
				//Vector3 root_pos = node->getPosition();//get root pos
				Ogre::Vector3 direction = ovm->getPosition();//compute direction				
				if(direction.normalisedCopy().directionEquals(Ogre::Vector3(-1,-1,0),Ogre::Radian(Ogre::Degree(45)))){
					//directionEquals第一個參數是你想compare的方向,第二個參數是可容忍的角度(以right hand side來看
					//以 (-1,-1,0) 往 rhs算45度 , 都算是同一個方向 , 由於DIVA的left or right node都擺在相對於root的45度
					ordered_child.push_back(make_pair(0,(*it)));
				}
				else if(direction.normalisedCopy().directionEquals(Ogre::Vector3(1,-1,0),Ogre::Radian(Ogre::Degree(45)))){
					ordered_child.push_back(make_pair(1,(*it)));
				}
				else{
					assert(direction == Ogre::Vector3(50,-50,0) || direction == Ogre::Vector3(-50,-50,0));
				}
			}
		}
	}
	if(childs.size() != 0){
		_links[node] = ordered_child;
	}
}

void BinaryTree_Dynamic_Lyvm::earseLinks(){
	/*clean links*/
	_links.clear();
	_levels.clear();
	_record.clear();
}
void BinaryTree_Dynamic_Lyvm::searchRoot(vector<DIVA_VM*> vms){
	/*vector<DIVA_VM*>::iterator it;
	map<int,vector<DIVA_VM*>> childs_count;
	for(it = vms.begin() ; it != vms.end() ; ++it){
		vector<DIVA_VM*> childs = xVMRelationStruct::getInstance()->VMRS_nextVMsByRef((*it));
		childs_count[childs.size()].push_back((*it));
	}
	pair<int,vector<DIVA_VM*>> itr;
	itr = *(max_element(childs_count.begin(),childs_count.end(),getMax));
	this->_root = *(itr.second.begin());
	*/
	//往上找parent , 如果parent是與本身相同type的composite VM, 那本身就不是root , 
	//root的parent必為不同type的composite, how to determine type?
	//查wop?
	vector<DIVA_VM*>::iterator it;
	for(it = vms.begin() ; it != vms.end() ; ++it){
		vector<DIVA_VM*> parents = xVMRelationStruct::getInstance()->VMRS_preVMsByRef((*it));
		vector<DIVA_VM*>::iterator itr;
		for(itr = parents.begin() ; itr != parents.end() ; ++itr){
			DIVA_VM* vm = xVMRelationStruct::getInstance()->VMRS_toCompositeRootVM((*itr));
			if(vm == (*itr)){
				if(this->_root != NULL){
					(*it)->setPosition(this->_root->getPosition());
				}
				this->_root = (*it);
			}
		}
	}	
}
void BinaryTree_Dynamic_Lyvm::layout(vector<DIVA_VM*> nodes,DIVA_VM* movedVM){
	/*外部只要給需要被排列的node,這邊就會產生出每個node的position*/
	searchRoot(nodes); //考慮到如果root被移除或取代 , 要重新找一次root
	earseLinks();
	vector<DIVA_VM*>::iterator it;
	for(it = nodes.begin() ; it != nodes.end() ; ++it){
		constructLinks((*it));
	}
	arrangeChildsByLevel();
	int max_level = _levels.size();
	for(int i=0 ; i <max_level ; i++){
		vector<DIVA_VM*> roots = _levels[i];
		vector<DIVA_VM*>::iterator itr;
		for(itr = roots.begin() ; itr != roots.end() ; ++itr){			
			vector<pair<int,DIVA_VM*>> childs = searchChildFromLink((*itr));
			determineChildsPosition((*itr),childs,max_level-i);
		}
	}
	//assert(_record.size() == nodes.size());
}




void BinaryTree_Dynamic_Lyvm::behavior(float timeSinceLastFrame){
	if(!_flag) return;
	if(_area != NULL){
		delete _area;
		_area = new Ly_influence_area(_root, bRefIn, bRefOut, valuableNames, level);
	}
	layout(_area->getAllVMs(),_root);//_root沒作用	
	setChanges();
}